home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HyperLib 1997 Winter - Disc 1
/
HYPERLIB-1997-Winter-CD1.ISO.7z
/
HYPERLIB-1997-Winter-CD1.ISO
/
オンラインウェア
/
PRG
/
Clut fade 1.3.2 Folder.sit
/
Clut fade 1.3.2 Folder
/
clut_fade 1.3.2
/
Pascal
/
fade.p
< prev
next >
Wrap
Text File
|
1996-04-25
|
17KB
|
545 lines
unit Fade;
interface
{/******************************************************************************** }
{ }
{ PROJECT: clut_fade.ケ }
{ }
{ FILE: fade.p }
{ }
{ PURPOSE: 'clut' fading functions }
{ }
{ ??/??/93 1.0 written by N. Jonas Englund }
{ 07/26/94 1.1 Changes by Mark Womack to allow fading all monitors, only the }
{ main monitor, or all monitors except the main monitor. Cleaned }
{ up the fade.h to hide more structures, and removed almost all global }
{ space used (My changes grew the global space by 10 times so I figured }
{ it needed to be fixed). Current code is limited to 10 monitors max, }
{ but is easily cofigurable for more if you think you need it. }
{ 10/21/94 Changes by Mark Womack to make pascal friendly, fix < 256 color }
{ crasher, cleaned up to make more readable. }
{ 10/24/94 Integrated fade_to_clut function written by Macneil Shonle. }
{ Added copy_gdevice_clut function to make it easier to save }
{ and restore device clut's. }
{ Added fade_to_color function which uses both the fade_to_clut }
{ and copy_gdevice_clut functions to fade to a given rgb value. }
{ 03/05/96 Translated to Pascal by C. Franz (cfranz@home.malg.imp.com) }
{ Written for THINK Pascal. To port to other Pascal dialects you }
{ must check what the 'continue' command in C corresponds to. It's }
{ 'CYCLE' in THINK Pascal }
{ }
{ =-=-= PLEASE SEE THE README THAT ACCOMPANIED THIS PROJECT FOR DETAILS =-=-= }
{ }
{ This software is considered Public Domain. You are free to use it in any }
{ manner you wish. You are free to upload it to your favorite service, but }
{ you must post it with the accompanying readme and description files. }
{ If you use or appreciate it, please let us know!! We all love to get email. }
{ See the addresses below. }
{ }
{ This software is offered 'as is'. The authors are not responsible for any }
{ damages caused by bugs or defects that might be lurking. But if it blows up }
{ your monitor, please let us know. If you find any bugs, problems, enhancements, }
{ please contact us. }
{ }
{ Email Addresses: MarkWomack@aol.com, MacneilS@aol.com, KenLong@aol.com. }
{ }
{ ********************************************************************************/ }
const
fadeMainOnly = 1; {#define fadeMainOnly 1}
fadeAll = 2; {#define fadeAll 2}
fadeAllButMain = 4; {#define fadeAllButMain 4}
const
MAXCOLORS = 256;
gMaxDevices = 10;
type {typedef struct FadeValues}
FadeValues = record
reds: array[0..255] of integer;
greens: array[0..255] of integer;
blues: array[0..255] of integer;
end; {FadeValues;}
{//===== PUBLIC FUNCTIONS =====//}
{ These are the actual 'work' procedures }
procedure fade_to_black (numSteps: longint; fadeFlags: integer; fadeOut: boolean);
procedure fade_to_clut (numSteps: longint; destTab: CTabHandle; aGDevice: GDHandle);
procedure fade_to_color (numSteps: longint; var destColor: RGBColor; aGDevice: GDHandle);
{ some misc procedures to manipulate CLUTs }
procedure copy_gdevice_clut (aGDevice: GDHandle; var copyOfClut: CTabHandle);
{ returns a handle to a newly allocated copy of clut }
procedure copy_cluts (hGD: GDHandle; var gFade: CTabHandle; var gOrig: CTabHandle);
{ given a GDevice, it returns the devices CLUT in gFade and a Handle to a newly }
{ allocated copy in gOrig }
implementation
{//================================= FUNCTIONS =================================== }
{ Remember, the fade routines are translated from C. }
{ Because C is arcane we need to forward declare some functions. }
{ because of this, we simply define them in the Interface section, so they can be }
{ accessed internally }
procedure calc_fade (numSteps: longint; gFade: CTabHandle; var rgbs: FadeValues);
FORWARD;
procedure fade_out (fadeLevel: longint; gFade: CTabHandle; rgbs: FadeValues);
FORWARD;
procedure fade_in (fadeLevel: longint; gFade: CTabHandle; gOrig: CTabHandle; rgbs: FadeValues);
FORWARD;
procedure black_out (gFade: CTabHandle);
FORWARD;
procedure restore_clut (gFade: CTabHandle; gOrig: CTabHandle);
FORWARD;
{/ ********************************** fade_to_black ****************************** /}
procedure fade_to_black (numSteps: longint; fadeFlags: integer; fadeOut: boolean);{pascal void fade_to_black(long numSteps, short fadeFlags, Boolean fadeOut)}
{}
var
oldDev, hGD: GDHandle;
gdHdls: array[0..gMaxDevices] of GDHandle;
rgbs: array[0..gMaxDevices] of FadeValues;
gFade: array[0..gMaxDevices] of CTabHandle;
gOrig: array[0..gMaxDevices] of CTabHandle;
x, numDevices, stepCount: integer;
stepper: integer; (* used to clean up convoluted C code FOR loop *)
notDone: Boolean; (* see above *)
begin
{// initialize}
oldDev := GetGDevice;
{now comes a cool expression in C: hGD = (!!(fadeFlags & fadeMainOnly != 0)) ? GetMainDevice() : GetDeviceList();}
{this resolves to }
if (BitAND(fadeFlags, fadeMainOnly) <> 0) then
hGD := GetMainDevice
else
hGD := GetDeviceList; {I really, really hate C. Why did they have to write such a convoluted }
{statement? It's *very* hard to understand, maintain or debug. What a }
{piece of crap. The pascal equivalent is much easier to understand. }
{Also, it generates *much* tighter object code... tsk, tsk. }
numDevices := 0;
{// make a list of the affected gdevices}
{ a typical C damned-if-you-can-read-me while: while (hGD && numDevices < gMaxDevices))}
while (hGD <> nil) and (numDevices < gMaxDevices) do
begin
{// skip main device if fadeAllButMain flag}
if TestDeviceAttribute(hGD, mainScreen) and (BitAND(fadeFlags, fadeAllButMain) <> 0) then
begin
hGD := hGD^^.gdNextGD;
cycle; {you can easily tell this was originally C code if I have to resort to }
end; {the cycle statement. }
if TestDeviceAttribute(hGD, screenDevice) then
begin
gdHdls[numDevices] := hGD;
numDevices := numDevices + 1;
end; { if }
{// stop now if only fading main device}
{if (!!(fadeFlags & fadeMainOnly != 0))}
{break;}
{hGD = (GDHandle)(*hGD)->gdNextGD;}
{previous extremely ugly code will be resolved to a much more }
{elegant method. Instead of jumping out of the loop, we fulfill }
{the break condition -- hGD equals NIL: }
if BitAND(fadeFlags, fadeMainOnly) <> 0 then
hGD := nil
else
hGD := hGD^^.gdNextGD;
end; { while }
{// calculate the fade cluts for each device}
x := 0;
while x < numDevices do
begin
SetGDevice(gdHdls[x]);
copy_cluts(gdHdls[x], gFade[x], gOrig[x]);
calc_fade(numSteps, gFade[x], rgbs[x]);
x := x + 1;
end; { while }
{// fade each device}
{// I know this is unreadable (dontcha love C?), the idea is to count down on}
{// fadeout and count up on fade in.}
{ well -- at least they admit it. It IS unreadable }
{eat this: }
{for (stepCount = fadeOut ? numSteps : 0; fadeOut ? stepCount >= 0 : stepCount < numSteps; fadeOut ? stepCount-- : stepCount++)}
{I resolved this stupid code the following way: }
{ stepper -- holds either -1 (count down for fade out ) or 1 (count up) }
{ notDone -- true until we went through all steps}
if fadeOut then
stepcount := numSteps
else
stepCount := 0;
if fadeOut then
stepper := -1
else
stepper := 1; (* no equivalent *)
if fadeOut then
notDone := stepCount >= 0
else
notDone := stepCount < numSteps; (* no equivalent - used to clean up loop *)
while notDone do
begin
x := 0;
while x < numDevices do
begin
SetGDevice(gdHdls[x]);
if fadeOut then
fade_out(stepCount, gFade[x], rgbs[x])
else
fade_in(stepCount, gFade[x], gOrig[x], rgbs[x]);
x := x + 1;
end;
stepCount := stepCount + stepper;
if fadeOut then
notDone := stepCount >= 0
else
notDone := stepCount < numSteps;
end; {baaad for loop -- while not done}
{// restore each devices clut, and dispose of temp memory}
x := 0;
while x < numDevices do
begin
SetGDevice(gdHdls[x]);
restore_clut(gFade[x], gOrig[x]);
DisposeHandle(Handle(gOrig[x]));
x := x + 1;
end;
{// set original device}
SetGDevice(oldDev);
end;
procedure AdjustOne (var rgb: integer; delta: integer);
var
theColor: longint;
begin
theColor := BitAND(rgb, $0000FFFF);
theColor := theColor - delta;
rgb := loword(theColor);
end;
{/ *********************************** fade_to_clut ******************************* /}
procedure fade_to_clut (numSteps: longint; destTab: CTabHandle; aGDevice: GDHandle);
{}
var
srcTab: CTabHandle; { // get the monitorユs current clut}
redDelta: array[0..MaxColors] of longint; {// We want the range for each color to be of an}
greenDelta: array[0..MaxColors] of longint; {// unsigned short, but we need negative numbers.}
blueDelta: array[0..MaxColors] of longint; {// So these longs are the solution.}
difference: longint; {// used to clear up clutter in the code}
i: longint; {// to cycle trough for loops}
colorIndex: longint; {// to cycle through arrays}
oldGDevice: GDHandle;
l1, l2: longint; {pascal conversion}
begin
srcTab := aGDevice^^.gdPMap^^.pmTable;
oldGDevice := GetGDevice;
SetGDevice(aGDevice); {// set it to the monitor to be faded}
{ }
{ {/**** Set up the deltas ****/}
i := 0;
while i <= destTab^^.ctSize do
begin
{ /* This is what I am thinking: take the difference between the two colors and divide }
{ it by the number of steps (numSteps). So we will have a number that can be added }
{ to the source numSteps times and have it end up equaling the destination. }
{ */ }
l1 := BitAND(srcTab^^.ctTable[i].rgb.red, $0000FFFF); (* make it longint without going negative *)
l2 := BitAND(destTab^^.ctTable[i].rgb.red, $0000FFFF); (* same as above *)
difference := l1 - l2;
redDelta[i] := loword(difference div numSteps);
l1 := BitAND(srcTab^^.ctTable[i].rgb.green, $0000FFFF);
l2 := BitAND(destTab^^.ctTable[i].rgb.green, $0000FFFF);
difference := l1 - l2;
greenDelta[i] := loword(difference div numSteps);
l1 := BitAND(srcTab^^.ctTable[i].rgb.blue, $0000FFFF);
l2 := BitAND(destTab^^.ctTable[i].rgb.blue, $0000FFFF);
difference := l1 - l2;
blueDelta[i] := loword(difference div numSteps);
i := i + 1;
end;
{/ **** Do the fade **** / }
i := 0;
while i < numSteps do
begin
colorIndex := 0;
while colorIndex <= destTab^^.ctSize do
begin
AdjustOne(srcTab^^.ctTable[colorIndex].rgb.red, redDelta[colorIndex]);
AdjustOne(srcTab^^.ctTable[colorIndex].rgb.green, greenDelta[colorIndex]);
AdjustOne(srcTab^^.ctTable[colorIndex].rgb.blue, blueDelta[colorIndex]);
colorIndex := colorIndex + 1;
end;
SetEntries(0, srcTab^^.ctSize, srcTab^^.ctTable);
i := i + 1;
end;
SetEntries(0, destTab^^.ctSize, destTab^^.ctTable);
srcTab^^.ctSeed := destTab^^.ctSeed; { set the ctSeed too }
MakeITable(nil, nil, 0);
SetGDevice(oldGDevice);
end;
procedure fade_to_color (numSteps: longint; var destColor: RGBColor; aGDevice: GDHandle);
{}
var
newColors: CTabHandle;
x: integer;
begin
{// get copy of the current color table}
copy_gdevice_clut(aGDevice, newColors);
{// make the color table all one color}
x := 0;
while x <= newColors^^.ctSize do
begin
newColors^^.ctTable[x].rgb := destColor;
x := x + 1;
end;
newColors^^.ctSeed := GetCTSeed; { change the ctSeed so we know it is different }
{// fade to the custom color table}
fade_to_clut(numSteps, newColors, aGDevice);
{// dispose color table}
DisposeHandle(Handle(newColors));
end;
procedure copy_gdevice_clut (aGDevice: GDHandle; var copyOfClut: CTabHandle);
var
srcTab: CTabHandle;
dummy: integer;
begin
srcTab := aGDevice^^.gdPMap^^.pmTable;
dummy := HandToHand(Handle(srcTab));
copyOfClut := srcTab;
end;
{ / / = = = = = PRIVATE FUNCTIONS = = = = = / /}
{/ ********************************** copy_cluts ********************************** /}
procedure copy_cluts (hGD: GDHandle; var gFade: CTabHandle; var gOrig: CTabHandle);
var
gTempH: Handle;
dummy: integer;
begin
gFade := hGD^^.gdPMap^^.pmTable;
gTempH := Handle(hGD^^.gdPMap^^.pmTable);
dummy := HandToHand(gTempH);
gOrig := CTabHandle(gTempH);
HLock(Handle(gFade));
HLock(Handle(gOrig));
end;
{/ *********************************** calc_fade ********************************** /}
procedure calc_fade (numSteps: longint; gFade: CTabHandle; var rgbs: FadeValues);
{}
var
i: integer;
calcval: longint;
begin
i := 0;
while i <= gFade^^.ctSize do
begin
calcval := bitAND(gFade^^.ctTable[i].rgb.red, $0000ffff);
calcval := calcval div numSteps;
rgbs.reds[i] := calcval;
calcval := bitand(gFade^^.ctTable[i].rgb.green, $0000ffff);
calcval := calcval div numSteps;
rgbs.greens[i] := calcval;
calcval := bitand(gFade^^.ctTable[i].rgb.blue, $0000ffff);
calcval := calcval div numSteps;
rgbs.blues[i] := calcval;
i := i + 1;
end;
end;
(* Help proc for conversion of integer to longint without extending hi-word *)
procedure fadeone (var rgbval: integer; difference: longint);
var
colorVal: longint;
begin
colorVal := bitAND(rgbVal, $0000FFFF);
if colorval > difference then
colorval := colorval - difference;
rgbval := loword(colorval);
end;
{/ ********************************** fade_out ********************************** /}
procedure fade_out (fadeLevel: longint; gFade: CTabHandle; rgbs: FadeValues);
{}
var
i: integer;
begin
i := 0;
while i < gFade^^.ctSize do
begin
fadeone(gFade^^.ctTable[i].rgb.red, rgbs.reds[i]);
fadeone(gFade^^.ctTable[i].rgb.green, rgbs.greens[i]);
fadeone(gFade^^.ctTable[i].rgb.blue, rgbs.blues[i]);
i := i + 1;
end;
SetEntries(0, gFade^^.ctSize, gFade^^.ctTable);
if fadeLevel = 0 then
black_out(gFade);
end;
{/ ********************************** fade_in ********************************** /}
procedure fadeinone (var rgb: integer; target: integer; increment: integer);
var
color1, color2: longint;
begin
color1 := BitAND(rgb, $0000FFFF);
color2 := BitAND(target, $0000FFFF);
if color1 < color2 then
color1 := color1 + increment;
rgb := loword(color1);
end;
procedure fade_in (fadeLevel: longint; gFade: CTabHandle; gOrig: CTabHandle; rgbs: FadeValues);
{}
var
i: integer;
begin
if fadeLevel = 0 then
black_out(gFade);
i := 0;
while i <= gFade^^.ctSize do
begin
fadeinone(gFade^^.ctTable[i].rgb.red, gOrig^^.ctTable[i].rgb.red, rgbs.reds[i]);
fadeinone(gFade^^.ctTable[i].rgb.green, gOrig^^.ctTable[i].rgb.green, rgbs.greens[i]);
fadeinone(gFade^^.ctTable[i].rgb.blue, gOrig^^.ctTable[i].rgb.blue, rgbs.blues[i]);
i := i + 1;
end;
SetEntries(0, gFade^^.ctSize, gFade^^.ctTable);
end;
{/********************************** black_out ********************************** /}
procedure black_out (gFade: CTabHandle);
{}
var
i: integer;
begin
i := 0;
while i < gFade^^.ctSize do
begin
gFade^^.ctTable[i].rgb.red := 0;
gFade^^.ctTable[i].rgb.green := 0;
gFade^^.ctTable[i].rgb.blue := 0;
i := i + 1;
end;
SetEntries(0, gFade^^.ctSize, gFade^^.ctTable);
end;
{ / ********************************** restore_clut ********************************** /}
procedure restore_clut (gFade: CTabHandle; gOrig: CTabHandle);
{}
var
i: integer;
begin
i := 0;{}
while i <= gFade^^.ctSize do
begin
gFade^^.ctTable[i].rgb.red := gOrig^^.ctTable[i].rgb.red;{}
gFade^^.ctTable[i].rgb.green := gOrig^^.ctTable[i].rgb.green;{}
gFade^^.ctTable[i].rgb.blue := gOrig^^.ctTable[i].rgb.blue;{}
i := i + 1;
end;
gFade^^.ctSeed := gOrig^^.ctSeed; { restore the ctSeed too }
MakeITable(nil, nil, 0);
HUnlock(Handle(gFade));
HUnlock(Handle(gOrig));
end;
end.